﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using NexTrackDesktop.Media;
using System.Windows;
using System.Collections.ObjectModel;
using System.Windows.Input;
using Microsoft.Win32;
using System.Threading;
using System.IO;
using System.Windows.Threading;

namespace NexTrackDesktop.ViewModels
{
    /// <summary>
    /// This class handles events for the MediaLibrary view
    /// </summary>
    public class MediaLibraryViewModel : ViewModelBase
    {
        private Library library;
        private Dispatcher Dispatcher;

        public ObservableCollection<SongViewModel> Songs { get; private set; }

        public ICommand AddMediaCommand { get; private set; }
        public ICommand AddFolderCommand { get; private set; }
        public ICommand AddToPlaylistCommand { get; private set; }

        public IEnumerable<SongViewModel> SelectedSongs
        {
            get { return Songs.Where(s => s.Selected); }
        }

        public MediaLibraryViewModel()
        {
            Dispatcher = Dispatcher.CurrentDispatcher;

            library = new Library();
            Songs = new ObservableCollection<SongViewModel>();
            library.SongAdded += new Action<Song>(library_SongAdded);

            createCommands();
        }

        /// <summary>
        /// This method adds the specified Song to the views oberservable collection
        /// </summary>
        /// <param name="song">Song to add to collection</param>
        void library_SongAdded(Song song)
        {
            Dispatcher.Invoke((Action)(() =>
            {
                Songs.Add(new SongViewModel(song));
            }));
        }

        /// <summary>
        /// This method links commands with user input for the view
        /// </summary>
        void createCommands()
        {
            AddMediaCommand = new DelegateCommand(addMedia, () => true);
            AddFolderCommand = new DelegateCommand(addFolder, () => true);
            AddToPlaylistCommand = new DelegateCommand(addToPlaylist,
                () => Client.Party != null && SelectedSongs.Count() > 0);
        }

        /// <summary>
        /// This method handles adding media to library through file dialog
        /// </summary>
        void addMedia()
        {
            OpenFileDialog ofd = new OpenFileDialog();
            ofd.Filter = "Music Files|*.mp3; *.mp4; *.m4a; *.ogg; *.flac; *.cda; *.wma|All Files|*.*";
            ofd.CheckFileExists = true;
            ofd.CheckPathExists = true;
            ofd.Multiselect = true;
            ofd.InitialDirectory = "shell:My Music";

            if (ofd.ShowDialog() == true)
            {
                foreach (string file in ofd.FileNames)
                {
                    library.AddFile(new Uri(file));
                }
            }
        }

        /// <summary>
        /// This method handles adding media to library through folder dialog
        /// </summary>
        void addFolder()
        {
            System.Windows.Forms.FolderBrowserDialog fbd = new System.Windows.Forms.FolderBrowserDialog();
            fbd.RootFolder = Environment.SpecialFolder.MyMusic;
            fbd.ShowNewFolderButton = false;

            if (fbd.ShowDialog() == System.Windows.Forms.DialogResult.OK)
            {
                //hack for background thread
                Action<object> threadStart = (o) => { library.addFolderRecursive(o as string); };
                Thread t = new Thread(new ParameterizedThreadStart(threadStart));
                t.Start(fbd.SelectedPath);
            }
        }

        /// <summary>
        /// This method adds selected songs to playlist
        /// </summary>
        void addToPlaylist()
        {
            Client.Party.Playlist.AddSongs(SelectedSongs.Where(s => s.Selected).Select(s => s.Song));
        }
    }
}
